home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 117 (1989-11-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 117 (1989-11-15)(Ossowski, Stefan)(DE)(PD).adf / AlarmingClock / AlarmingClock.c < prev    next >
C/C++ Source or Header  |  1989-08-20  |  25KB  |  845 lines

  1. /*
  2. **       alarming_clock             -- by Brian Neal   6/24/89
  3. **
  4. **    A simple clock program whoose alarm packs a punch!  Be sure to
  5. **    crank up the stereo for this one.  Illustrates the use of the
  6. **    timer and digitized sound playback.
  7. **    Compiled with Manx Aztec C v3.6
  8. **           cc -n alarming_clock
  9. **           ln -g alarming_clock isup -lc
  10. */
  11.  
  12. #include <intuition/intuition.h>
  13. #include <functions.h>
  14. #include <devices/audio.h>
  15. #include <devices/timer.h>
  16. #include <exec/memory.h>
  17. #include <libraries/dos.h>
  18.  
  19. /*  useful macros */
  20. #define CHAR_WIDTH  (font -> tf_XSize)
  21. #define CHAR_HEIGHT (font -> tf_YSize)
  22.  
  23. #define WIN_WIDTH 200      /* window constants */
  24. #define WIN_HEIGHT 60
  25.  
  26. #define BUTT_WIDTH  50     /* gadget constants */
  27. #define BUTT_HEIGHT 14
  28.  
  29. #define TEST    1          /* GadgetIDs */
  30. #define ALARM   2
  31. #define UP      3
  32. #define DOWN    4
  33. #define HRS_TEN 5
  34. #define HRS_ONE 6
  35. #define MIN_TEN 7
  36. #define MIN_ONE 8
  37.  
  38. #define ARROW_WIDTH  16     /* arrow dimensions */
  39. #define ARROW_HEIGHT 8
  40.  
  41. #define MAPRIGHT 0x00000006      /* masks for channel allocation */
  42. #define MAPLEFT  0x00000009
  43.  
  44. #define SCREAM_PERIOD 400
  45. #define SCREAM_LENGTH 12536      /* length (in bytes) of data file */
  46.                                  /* used CLI's List to get this    */
  47. #define POW_PERIOD 475
  48. #define POW_LENGTH 23632
  49.  
  50. #define CLOCK_LEFT  ((WIN_WIDTH - (5 * CHAR_WIDTH)) / 2)
  51. #define CLOCK_TOP   12
  52.  
  53. #define ALARM_LEFT  CLOCK_LEFT
  54. #define ALARM_TOP   24
  55.  
  56.  
  57. extern BOOL open_libraries();
  58. extern struct Window *make_window();
  59. extern void init_itext(), *copy_chip();
  60.  
  61. void shut_down(), init_sounds(), shut_down_audio(), display_time(),
  62.      shut_down_timer(), send_time_request(), init_arrow(), init_image(),
  63.      set_up_display(), sound_alarm(), display_alarm(),
  64.      turn_off_alarm(), init_digit(), adjust_alarm();
  65. UBYTE init_audio();
  66. BOOL read_data(), init_timer(), set_up_window(), time_to_sound(),
  67.      set_up_gadgets();
  68.  
  69. struct IntuiText test_text, alarm_text, clock_face, alarm_face;
  70. struct Gadget arrow[2];
  71. struct Gadget digit[4];
  72. struct Image  arrow_image[2];
  73.  
  74. #define ARROW_BYTES 16
  75. USHORT up_image[] = { 0x0000, 0x0180, 0x03c0, 0x07e0,
  76.                       0x0ff0, 0x1ff8, 0x7ffe, 0x0000 };
  77.  
  78. USHORT down_image[] = { 0x0000, 0x7ffe, 0x1ff8, 0x0ff0,
  79.                         0x07e0, 0x03c0, 0x0180, 0x0000 };
  80.  
  81.  
  82. SHORT points[] = { -1, -1,     BUTT_WIDTH, -1,
  83.                    BUTT_WIDTH, BUTT_HEIGHT,
  84.                    -1, BUTT_HEIGHT,    -1, -1 };
  85.  
  86. struct Border butt_border =
  87. {  0, 0,                                  /*  LeftEdge, TopEdge */
  88.    3, 0,                                  /*  FrontPen, BackPen */
  89.    JAM1,                                  /*  DrawMode          */
  90.    5,                                     /*  Count             */
  91.    &points[0],                            /*  XY                */
  92.    NULL };                                /*  NextBorder        */
  93.  
  94.  
  95. struct Gadget test_button =
  96. {  NULL,                                  /*  NextGadget        */
  97.    20, -(BUTT_HEIGHT + 5),                /*  LeftEdge, TopEdge */
  98.    BUTT_WIDTH, BUTT_HEIGHT,               /*  Width, Height     */
  99.    GADGHCOMP | GRELBOTTOM,                /*  Flags             */
  100.    GADGIMMEDIATE | RELVERIFY,             /*  Activation        */
  101.    BOOLGADGET,                            /*  GadgetType        */
  102.    (APTR) &butt_border,                   /*  GadgetRender      */
  103.    NULL,                                  /*  SelectRender      */
  104.    &test_text,                            /*  GadgetText        */
  105.    0L,                                    /*  MutualExclude     */
  106.    NULL,                                  /*  SpecialInfo       */
  107.    TEST,                                  /*  GadgetID          */
  108.    NULL };                                /*  UserData          */
  109.  
  110. struct Gadget alarm_button =
  111. {  &test_button,
  112.    -(BUTT_WIDTH + 20), -(BUTT_HEIGHT + 5),
  113.    BUTT_WIDTH, BUTT_HEIGHT,
  114.    GADGHCOMP | GRELRIGHT | GRELBOTTOM,
  115.    GADGIMMEDIATE | TOGGLESELECT,
  116.    BOOLGADGET,
  117.    (APTR) &butt_border,
  118.    NULL,
  119.    &alarm_text,
  120.    0L,
  121.    NULL,
  122.    ALARM,
  123.    NULL };
  124.  
  125. /*  We are going to use topaz.font 80  */
  126. struct TextAttr our_font =
  127. {  (STRPTR) "topaz.font",              /*      ta_Name      */
  128.    8,                                  /*      ta_YSize     */
  129.    FS_NORMAL,                          /*      ta_Style     */
  130.    FPB_ROMFONT };                      /*      ta_Flags     */
  131.  
  132.  
  133. struct my_time             /* hours in range of 0..24, minutes in 0..59 */
  134. {
  135.    UBYTE hours, minutes;
  136. };
  137.  
  138. struct IntuitionBase *IntuitionBase = NULL;
  139. struct GfxBase       *GfxBase       = NULL;
  140. struct TextFont      *font          = NULL;
  141.  
  142.  
  143.  
  144.  
  145. void main()
  146. {
  147.    struct Window *win = NULL;
  148.    struct IntuiMessage *msg;
  149.    struct IOAudio scream, pow;
  150.    UBYTE channel_mask;
  151.    UBYTE *scream_data = NULL, *pow_data = NULL;
  152.    struct timerequest time_req;
  153.    struct my_time current, alarm;
  154.    struct Gadget *gad;
  155.    ULONG class;
  156.    USHORT active_digit;
  157.    BOOL alarm_set, gad_images = FALSE;
  158.  
  159.       if (!(open_libraries(33L, 33L)))
  160.          shut_down(10, win, scream_data, pow_data, gad_images);
  161.  
  162.       if (!(font = (struct TextFont *) OpenFont(&our_font)))
  163.          shut_down(20, win, scream_data, pow_data, gad_images);
  164.  
  165.       if (!(read_data(&scream_data, &pow_data)))
  166.          shut_down(30, win, scream_data, pow_data, gad_images);
  167.  
  168.       if (!(gad_images = set_up_gadgets()))
  169.          shut_down(40, win, scream_data, pow_data, gad_images);
  170.  
  171.       if (!set_up_window(&win))
  172.          shut_down(50, win, scream_data, pow_data, gad_images);
  173.  
  174.       if ((channel_mask = init_audio(&scream)) == 0)
  175.          shut_down(60, win, scream_data, pow_data, gad_images);
  176.  
  177.       init_sounds(&scream, &pow, channel_mask, scream_data, pow_data);
  178.  
  179.       if (!(init_timer(&time_req)))
  180.       {
  181.          shut_down_audio(&scream, channel_mask);
  182.          shut_down(70, win, scream_data, pow_data, gad_images);
  183.       }
  184.  
  185.       set_up_display(win, &clock_face, &alarm_face);
  186.  
  187.       /*  Give us a boost in priority  */
  188.       SetTaskPri(FindTask(NULL), 20L);
  189.  
  190.       alarm_set = FALSE;
  191.       active_digit = MIN_ONE;
  192.       alarm.hours   = 0;
  193.       alarm.minutes = 0;
  194.       display_time(win, &clock_face, ¤t);
  195.       display_alarm(win, &alarm_face, alarm);
  196.       send_time_request(&time_req);
  197.  
  198.       FOREVER
  199.       {
  200.          /*
  201.          * if our time request is back, update clock and restart the
  202.          * timer.  If alarm is set, and it is that magic time, sound
  203.          * the alarm.
  204.          */
  205.          if (GetMsg(time_req.tr_node.io_Message.mn_ReplyPort))
  206.          {
  207.             display_time(win, &clock_face, ¤t);
  208.             send_time_request(&time_req);
  209.  
  210.             if ((time_to_sound(current, alarm)) && alarm_set)
  211.                sound_alarm(win, &scream, &pow);
  212.          }
  213.  
  214.          /*  Wait on timer and input from user via window */
  215.  
  216.          Wait(1L << win -> UserPort -> mp_SigBit |
  217.               1L << time_req.tr_node.io_Message.mn_ReplyPort -> mp_SigBit);
  218.  
  219.          while (msg = (struct IntuiMessage *) GetMsg(win -> UserPort))
  220.          {
  221.             class = msg -> Class;
  222.             gad = (struct Gadget *) msg -> IAddress;
  223.             ReplyMsg(msg);
  224.  
  225.             switch (class)
  226.             {
  227.                case CLOSEWINDOW:
  228.                   shut_down_timer(&time_req);
  229.                   shut_down_audio(&scream, channel_mask);
  230.                   shut_down(0, win, scream_data, pow_data, gad_images);
  231.                   break;
  232.  
  233.                case GADGETUP:    /*  has no meaning; set in gadgets  */
  234.                   break;         /*  only to let user see GADGHCOMP  */
  235.  
  236.                case GADGETDOWN:
  237.                   switch(gad -> GadgetID)
  238.                   {
  239.                      case ALARM:
  240.                         if (alarm_set)
  241.                         {
  242.                            turn_off_alarm(&alarm_button, win);
  243.                            alarm_set = FALSE;
  244.                         }
  245.                         else
  246.                            alarm_set = TRUE;
  247.                         break;
  248.  
  249.                      case TEST:
  250.                         sound_alarm(win, &scream, &pow);
  251.                         break;
  252.  
  253.                      case UP:
  254.                      case DOWN:
  255.                         adjust_alarm(&alarm, active_digit, gad -> GadgetID);
  256.                         display_alarm(win, &alarm_face, alarm);
  257.                         break;
  258.  
  259.                      case HRS_TEN:
  260.                      case HRS_ONE:
  261.                      case MIN_TEN:
  262.                      case MIN_ONE:
  263.                         active_digit = gad -> GadgetID;
  264.                         break;
  265.                   }
  266.                   break;
  267.  
  268.                default:
  269.                   break;
  270.             }                 /*  switch */
  271.          }                    /*  while  */
  272.       }                       /* for(;;) */
  273. }                             /*   main  */
  274.  
  275.  
  276. /*
  277. **       shut_down()
  278. **          Frees up everything but audio and timer related activiy.
  279. **/
  280.  
  281. void shut_down(code, win, scream, pow, gad_images)
  282. WORD code;
  283. struct Window *win;
  284. UBYTE *scream, *pow;
  285. BOOL gad_images;
  286. {
  287.    struct IntuiMessage *msg;
  288.  
  289.       if (gad_images)
  290.       {
  291.          FreeMem(arrow_image[0].ImageData, (ULONG) ARROW_BYTES);
  292.          FreeMem(arrow_image[1].ImageData, (ULONG) ARROW_BYTES);
  293.       }
  294.       if (pow)
  295.          FreeMem(pow, (ULONG) POW_LENGTH);
  296.       if (scream)
  297.          FreeMem(scream, (ULONG) SCREAM_LENGTH);
  298.       if (win)
  299.       {
  300.          while(msg = (struct IntuiMessage *) GetMsg(win -> UserPort))
  301.             ReplyMsg(msg);
  302.          CloseWindow(win);
  303.       }
  304.       if (font)
  305.          CloseFont(font);
  306.       if (GfxBase)
  307.          CloseLibrary(GfxBase);
  308.       if (IntuitionBase)
  309.          CloseLibrary(IntuitionBase);
  310.       Exit((LONG) code);
  311. }
  312.  
  313. /*
  314. **    shut_down_audio()
  315. **          Cleans up after using audio.device.
  316. */
  317.  
  318. void shut_down_audio(scream, channels_used)
  319. struct IOAudio *scream;
  320. UBYTE channels_used;
  321. {
  322.       scream -> ioa_Request.io_Unit = (struct Unit *) channels_used;
  323.       CloseDevice(scream);
  324.       DeletePort(scream -> ioa_Request.io_Message.mn_ReplyPort);
  325.       /* remember, pow and scream shared the same reply port */
  326. }
  327.  
  328.  
  329. /*
  330. **    init_audio()
  331. **          Opens audio device and allocates a stereo pair of channels.
  332. **       Returns a mask of channels allocated, or 0 if error.
  333. */
  334. UBYTE init_audio(iob)
  335. struct IOAudio *iob;
  336. {
  337.    UBYTE channel_map[4];
  338.    LONG error;
  339.    ULONG mask;
  340.  
  341.       channel_map[0] = 0x03;     /* channels 0 and 1 */
  342.       channel_map[1] = 0x05;     /* channels 0 and 2 */
  343.       channel_map[2] = 0x0a;     /* channels 3 and 1 */
  344.       channel_map[3] = 0x0c;     /* channels 3 and 2 */
  345.  
  346.       /* Get a reply port so the audio device can communicate with us */
  347.  
  348.       if ((iob -> ioa_Request.io_Message.mn_ReplyPort
  349.                                         = CreatePort("ac", 0L)) == NULL)
  350.          return (0);
  351.  
  352. /* We are now going to be pigs and set our priority to the max.  If
  353. *  successful, we hold exclusive access to our stereo pair of channels.
  354. *  Why don't we just set our priority lower, allocate channels, and then
  355. *  lock them?  Because we don't intend to give up our access until
  356. *  we quit.
  357. */
  358.       iob -> ioa_Request.io_Message.mn_Node.ln_Pri = ADALLOC_MAXPREC;
  359.       iob -> ioa_Data = &channel_map[0];
  360.       iob -> ioa_Length = 4L;
  361.  
  362.       error = OpenDevice(AUDIONAME, 0L, iob, 0L);
  363.       if (error == 0)
  364.       {
  365.          mask = (ULONG) iob -> ioa_Request.io_Unit;
  366.          return ((UBYTE) mask);
  367.       }
  368.       else
  369.       {
  370.          DeletePort(iob -> ioa_Request.io_Message.mn_ReplyPort);
  371.          return (0);
  372.       }
  373. }
  374.  
  375. /*
  376. **    init_sounds()
  377. **          Initializes our IOAudio request blocks for sounding
  378. **    once.  Attaches waveform data.
  379. */
  380.  
  381. void init_sounds(scream, pow, channel_mask, scream_data, pow_data)
  382. struct IOAudio *scream, *pow;
  383. UBYTE channel_mask;
  384. UBYTE *scream_data, *pow_data;
  385. {
  386.  
  387.       scream -> ioa_Request.io_Unit = (struct Unit *)
  388.                                       ((ULONG) channel_mask & MAPRIGHT);
  389.       scream -> ioa_Request.io_Command = CMD_WRITE;
  390.       scream -> ioa_Request.io_Flags = IOF_QUICK | ADIOF_PERVOL;
  391.       scream -> ioa_Data = scream_data;
  392.       scream -> ioa_Cycles = 1;
  393.       scream -> ioa_Period = SCREAM_PERIOD;
  394.       scream -> ioa_Length = (ULONG) SCREAM_LENGTH;
  395.       scream -> ioa_Volume = 64;
  396.  
  397.       /* copy keys, ports, and above stuff */
  398.       *pow = *scream;
  399.  
  400.       /* Now, more specifically... */
  401.       pow -> ioa_Request.io_Unit = (struct Unit *)
  402.                                    ((ULONG) channel_mask & MAPLEFT);
  403.       pow -> ioa_Data = pow_data;
  404.       pow -> ioa_Period = POW_PERIOD;
  405.       pow -> ioa_Length = (ULONG) POW_LENGTH;
  406. }
  407.  
  408. /*
  409. **       read_data()
  410. **             Read in digitized sound files, placing them into
  411. **    Chip memory.  Note that the files are IFF, but treated as
  412. **    raw data.  Hopefully, won't be able to hear the 'pop' as the
  413. **    header information is played.  NOTE:  Would be simple
  414. **    to skip over the header.  A job for a future revision.
  415. **    Call AmigaDos directly, bypassing all that "ffunction" stuff.
  416. **    shut_down() is responsible for freeing up the allocated Chip
  417. **    memory, so don't have to worry about that here.
  418. */
  419.  
  420. BOOL read_data(screamptr, powptr)
  421. UBYTE **screamptr, **powptr;
  422. {
  423.    struct FileHandle *scream_file, *pow_file;
  424.    LONG scream_actual, pow_actual;
  425.  
  426.       *screamptr = AllocMem((ULONG) SCREAM_LENGTH, MEMF_CHIP);
  427.       *powptr = AllocMem((ULONG) POW_LENGTH, MEMF_CHIP);
  428.  
  429.       pow_file    = Open("explosion.sound", MODE_OLDFILE);
  430.       scream_file = Open("scream.sound", MODE_OLDFILE);
  431.  
  432.       if ((!scream_file) || (!pow_file) || (!(*screamptr)) || (!(*powptr)))
  433.       {
  434.          if (scream_file)
  435.                          Close(scream_file);
  436.          if (pow_file)
  437.                          Close(pow_file);
  438.          return (FALSE);
  439.       }
  440.  
  441.       scream_actual = Read(scream_file, *screamptr, (LONG) SCREAM_LENGTH);
  442.       pow_actual = Read(pow_file, *powptr, (LONG) POW_LENGTH);
  443.  
  444.       Close(scream_file);
  445.       Close(pow_file);
  446.  
  447.       if ((scream_actual != SCREAM_LENGTH) || (pow_actual != POW_LENGTH))
  448.          return (FALSE);
  449.       else
  450.          return (TRUE);
  451. }
  452.  
  453. /*
  454. **       init_timer()
  455. **             Initializes our time request and opens the timer
  456. **    device.
  457. */
  458.  
  459. BOOL init_timer(time_req)
  460. struct timerequest *time_req;
  461. {
  462.       /* obtain reply port so timer can signal us */
  463.       if (!(time_req -> tr_node.io_Message.mn_ReplyPort =
  464.                   CreatePort("ac_timer", 0L)))
  465.          return (FALSE);
  466.  
  467.       if (OpenDevice(TIMERNAME, UNIT_VBLANK, time_req, 0L) != NULL)
  468.       {
  469.          DeletePort(time_req -> tr_node.io_Message.mn_ReplyPort);
  470.          return (FALSE);
  471.       }
  472.       else
  473.       {
  474.          /* set up our time request so the timer will time time for us */
  475.          time_req -> tr_node.io_Command = TR_ADDREQUEST;
  476.          time_req -> tr_node.io_Flags   = IOF_QUICK;
  477.          return (TRUE);
  478.       }
  479. }
  480.  
  481.  
  482. /*
  483. **       display_time()
  484. **          Outputs the current time to our window.
  485. */
  486.  
  487. void display_time(win, clock_face, current)
  488. struct Window *win;
  489. struct IntuiText *clock_face;
  490. struct my_time *current;
  491. {
  492.    struct DateStamp now;
  493.    SHORT hours, minutes;
  494.    static char time_buffer[7];
  495.  
  496.          DateStamp(&now);        /* get system time from AmigaDos */
  497.  
  498.          hours   = now.ds_Minute / 60;
  499.          minutes = now.ds_Minute % 60;
  500.  
  501.          /* format our time display in the time_buffer */
  502.  
  503.          sprintf(&time_buffer[0], "%02d:%02d", hours, minutes);
  504.  
  505.          /* attach it to our IntuiText structure, and display it */
  506.  
  507.          clock_face -> IText = (UBYTE *) &time_buffer[0];
  508.          PrintIText(win -> RPort, clock_face, 0L, 0L);
  509.  
  510.          current -> hours   = hours;
  511.          current -> minutes = minutes;
  512. }
  513.  
  514.  
  515. /*
  516. **       display_alarm()
  517. **          Outputs the current setting of the alarm to our window.
  518. */
  519. void display_alarm(win, alarm_face, alarm)
  520. struct Window *win;
  521. struct IntuiText *alarm_face;
  522. struct my_time alarm;
  523. {
  524.    static char alarm_buffer[7];
  525.  
  526.       sprintf(&alarm_buffer[0], "%02d:%02d", alarm.hours, alarm.minutes);
  527.       alarm_face -> IText = (UBYTE *) &alarm_buffer[0];
  528.       PrintIText(win -> RPort, alarm_face, 0L, 0L);
  529. }
  530.  
  531.  
  532. /*
  533. **       shut_down_timer()
  534. **          Releases access to the timer device.
  535. */
  536.  
  537. void shut_down_timer(time_req)
  538. struct timerequest *time_req;
  539. {
  540.       AbortIO(time_req);
  541.       CloseDevice(time_req);
  542.       DeletePort(time_req -> tr_node.io_Message.mn_ReplyPort);
  543. }
  544.  
  545. /*
  546. **       send_time_request()
  547. **          Sends a message to the timer, telling it to signal us
  548. **    in five seconds.  Thus our clock can never be off from the system
  549. **    clock by more than five seconds.
  550. **
  551. */
  552.  
  553. void send_time_request(time_req)
  554. struct timerequest *time_req;
  555. {
  556.  
  557.       time_req -> tr_time.tv_secs  = 5L;
  558.       time_req -> tr_time.tv_micro = 0L;
  559.       BeginIO(time_req);
  560. }
  561.  
  562.  
  563. /*
  564. **    init_arrow()
  565. **          Initializes the alarm's set buttons.
  566. */
  567.  
  568. void init_arrow(arrow, id)
  569. struct Gadget *arrow;
  570. COUNT id;
  571. {
  572.    arrow -> NextGadget    = (id == 0) ? &arrow[1]
  573.                                       : &alarm_button;
  574.    arrow -> LeftEdge      = (id == 0) ? (ALARM_LEFT - (ARROW_WIDTH + 6))
  575.                                       : (ALARM_LEFT + (CHAR_WIDTH * 5) + 6);
  576.    arrow -> TopEdge       = ALARM_TOP;
  577.    arrow -> Width         = ARROW_WIDTH;
  578.    arrow -> Height        = ARROW_HEIGHT;
  579.    arrow -> Flags         = GADGHCOMP | GADGIMAGE;
  580.    arrow -> Activation    = GADGIMMEDIATE | RELVERIFY;
  581.    arrow -> GadgetType    = BOOLGADGET;
  582.    arrow -> GadgetRender  = (APTR) &arrow_image[id];
  583.    arrow -> SelectRender  = NULL;
  584.    arrow -> GadgetText    = NULL;
  585.    arrow -> MutualExclude = 0L;
  586.    arrow -> SpecialInfo   = NULL;
  587.    arrow -> GadgetID      = UP + id;
  588.    arrow -> UserData      = NULL;
  589. }
  590.  
  591.  
  592. /*
  593. **       init_image()
  594. **          Initializes the alarm set button's images.
  595. */
  596.  
  597. void init_image(arrow, id)
  598. struct Image *arrow;
  599. COUNT id;
  600. {
  601.    arrow -> LeftEdge   = 0;
  602.    arrow -> TopEdge    = 0;
  603.    arrow -> Width      = ARROW_WIDTH;
  604.    arrow -> Height     = ARROW_HEIGHT;
  605.    arrow -> Depth      = 1;
  606.    arrow -> ImageData  = (id == 0) ? &up_image[0] : &down_image[0];
  607.    arrow -> PlanePick  = 2;
  608.    arrow -> PlaneOnOff = 0;
  609.    arrow -> NextImage  = NULL;
  610. }
  611.  
  612.  
  613. /*
  614. **       init_digit()
  615. **          Initializes the alarm's digit gadgets.
  616. */
  617. void init_digit(d, id)
  618. struct Gadget *d;
  619. UCOUNT id;
  620. {
  621.    d -> NextGadget    = (id < 3) ? &digit[id + 1] : &arrow[0];
  622.  
  623.    if (id < 2)
  624.       d -> LeftEdge   = ALARM_LEFT + (id * CHAR_WIDTH);
  625.    else
  626.       d -> LeftEdge   = ALARM_LEFT + CHAR_WIDTH + (id * CHAR_WIDTH);
  627.  
  628.    d -> TopEdge       = ALARM_TOP;
  629.    d -> Width         = CHAR_WIDTH;
  630.    d -> Height        = CHAR_HEIGHT;
  631.    d -> Flags         = GADGHCOMP;
  632.    d -> Activation    = GADGIMMEDIATE | RELVERIFY;
  633.    d -> GadgetType    = BOOLGADGET;
  634.    d -> GadgetRender  = NULL;
  635.    d -> SelectRender  = NULL;
  636.    d -> GadgetText    = NULL;
  637.    d -> MutualExclude = 0L;
  638.    d -> SpecialInfo   = NULL;
  639.    d -> GadgetID      = HRS_TEN + id;
  640.    d -> UserData      = NULL;
  641. }
  642.  
  643.  
  644. /*
  645. **       set_up_window()
  646. **          Hides the details of opening the window from
  647. **    main().
  648. */
  649. BOOL set_up_window(win)
  650. struct Window **win;
  651. {
  652.  
  653.       if (!(*win = make_window(100, 60, WIN_WIDTH, WIN_HEIGHT, -1, -1,
  654.                                CLOSEWINDOW | GADGETUP | GADGETDOWN,
  655.                                  WINDOWCLOSE | ACTIVATE | WINDOWDRAG |
  656.                                  WINDOWDEPTH | SMART_REFRESH,
  657.                                NULL, NULL, NULL,
  658.                                NULL, NULL, 0, 0, 0, 0)))
  659.          return (FALSE);
  660.  
  661.       SetFont((*win) -> RPort, font);
  662.       SetWindowTitles(*win, (UBYTE *) "Alarming Clock", NULL);
  663.       AddGList(*win, &digit[0], -1L, -1L, NULL);
  664.       RefreshGList(&digit[0], *win, NULL, -1L);
  665.       return (TRUE);
  666. }
  667.  
  668. /*
  669. **          set_up_gadgets()
  670. **             Hides the details of initializing all of our gadgets
  671. **    from main().  Our gadget list looks like:
  672. **         digits -> arrows -> alarm_button -> test_button
  673. */
  674. BOOL set_up_gadgets()
  675. {
  676.    COUNT i;
  677.  
  678.       init_itext(&test_text, 1, 9, 3, "TEST");
  679.       init_itext(&alarm_text, 1, 5, 3, "ALARM");
  680.  
  681.       for (i = 0; i < 4; ++i)
  682.          init_digit(&digit[i], i);
  683.  
  684.       for (i = 0; i < 2; ++i)
  685.       {
  686.          init_arrow(&arrow[i], i);
  687.          init_image(&arrow_image[i], i);
  688.       }
  689.       arrow_image[0].ImageData = copy_chip(&up_image[0], ARROW_BYTES);
  690.       arrow_image[1].ImageData = copy_chip(&down_image[0], ARROW_BYTES);
  691.  
  692.       if ((arrow_image[0].ImageData) && (arrow_image[1].ImageData))
  693.          return (TRUE);
  694.       else
  695.       {
  696.          if (arrow_image[0].ImageData)
  697.             FreeMem(arrow_image[0].ImageData, (ULONG) ARROW_BYTES);
  698.          if (arrow_image[1].ImageData)
  699.             FreeMem(arrow_image[1].ImageData, (ULONG) ARROW_BYTES);
  700.          return (FALSE);
  701.       }
  702. }
  703.  
  704. /*
  705. **          set_up_display()
  706. **             Hides the details of "drawing" our clock face from
  707. **    main().
  708. */
  709. void set_up_display(win, clock_face, alarm_face)
  710. struct Window *win;
  711. struct IntuiText *clock_face, *alarm_face;
  712. {
  713.  
  714.       init_itext(clock_face, 1, CLOCK_LEFT, CLOCK_TOP, "");
  715.       init_itext(alarm_face, 3, ALARM_LEFT, ALARM_TOP, "");
  716.  
  717.       clock_face -> DrawMode = JAM2;     /* use both pens, so old junk  */
  718.       alarm_face -> DrawMode = JAM2;     /* gets erased when written on */
  719. }
  720.  
  721.  
  722. /*
  723. **          sound_alarm()
  724. **    Beeps screen, and brings window to the front.
  725. **    Sends off a scream request, waits for it to finish,
  726. **    then fires off the pow request.  Waits for it to finish, then
  727. **    returns.
  728. */
  729. void sound_alarm(win, scream, pow)
  730. struct Window *win;
  731. struct IOAudio *scream, *pow;
  732. {
  733.  
  734.       DisplayBeep(NULL);    /*  Beep everyone's screen, impolite */
  735.       WindowToFront(win);   /*  but hey, someone needs reminding */
  736.       BeginIO(scream);
  737.       WaitIO(scream);
  738.       BeginIO(pow);
  739.       WaitIO(pow);
  740. }
  741.  
  742.  
  743. /*
  744. **          time_to_sound()
  745. **             Returns true is current time == time alarm is supposed
  746. **    to go off.
  747. */
  748. BOOL time_to_sound(current, alarm)
  749. struct my_time current, alarm;
  750. {
  751.    return ((current.hours   == alarm.hours) &&
  752.            (current.minutes == alarm.minutes));
  753. }
  754.  
  755.  
  756. /*
  757. **          turn_off_alarm()
  758. **             Shuts off the alarm by deselecting the alarm gadget.
  759. **    Note that you can't simply change the gadget's flags and refresh,
  760. **    you have to remove it, change it's flags, add it, then refresh.
  761. */
  762. void turn_off_alarm(alarm_button, win)
  763. struct Gadget *alarm_button;
  764. struct Window *win;
  765. {
  766.       RemoveGadget(win, alarm_button);
  767.       alarm_button -> Flags &=  ~SELECTED;
  768.       AddGadget(win, alarm_button, -1L);
  769.       RefreshGList(alarm_button, win, NULL, 1L);
  770. }
  771.  
  772.  
  773. /*
  774. **          adjust_alarm()
  775. **             When user clicks on arrows, we come here and adjust
  776. **    our alarm display.  The variable active_digit keeps track of the
  777. **    digit being changed.  This is a big mess!!
  778. */
  779. void adjust_alarm(alarm, active_digit, direction)
  780. struct my_time *alarm;
  781. USHORT active_digit, direction;
  782. {
  783.  
  784.       switch(active_digit)
  785.       {
  786.          case HRS_TEN:
  787.             if (direction == UP)
  788.             {
  789.                if (alarm -> hours >= 14)
  790.                   alarm -> hours = 0;
  791.                else
  792.                   alarm -> hours += 10;
  793.             }
  794.             else
  795.             {
  796.                if (alarm -> hours < 9)
  797.                   alarm -> hours = 23;
  798.                else
  799.                   alarm -> hours -= 10;
  800.             }
  801.             break;
  802.  
  803.          case HRS_ONE:
  804.             if (direction == UP)
  805.                alarm -> hours = (alarm -> hours + 1) % 24;
  806.             else
  807.             {
  808.                if (alarm -> hours == 0)
  809.                   alarm -> hours = 23;
  810.                else
  811.                   --alarm -> hours;
  812.             }
  813.             break;
  814.  
  815.          case MIN_TEN:
  816.             if (direction == UP)
  817.             {
  818.                if (alarm -> minutes > 49)
  819.                   alarm -> minutes = 0;
  820.                else
  821.                   alarm -> minutes += 10;
  822.             }
  823.             else
  824.             {
  825.                if (alarm -> minutes < 10)
  826.                   alarm -> minutes = 59;
  827.                else
  828.                   alarm -> minutes -= 10;
  829.             }
  830.             break;
  831.  
  832.          case MIN_ONE:
  833.             if (direction == UP)
  834.                alarm -> minutes = (alarm -> minutes + 1) % 60;
  835.             else
  836.             {
  837.                if (alarm -> minutes == 0)
  838.                   alarm -> minutes = 59;
  839.                else
  840.                   --alarm -> minutes;
  841.             }
  842.             break;
  843.          }
  844. }
  845.